package top.huntwolf.admin.service;


import com.github.pagehelper.Page;
import com.github.pagehelper.PageInfo;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import top.huntwolf.admin.common.enums.CodeMsg;
import top.huntwolf.admin.common.enums.OrderStatus;
import top.huntwolf.admin.dao.WxPayNotifyDao;
import top.huntwolf.admin.dao.WxPayRefundDao;
import top.huntwolf.admin.exception.ServiceException;
import top.huntwolf.admin.pojo.orderEntity.Order;
import top.huntwolf.admin.pojo.wxPay.*;
import top.huntwolf.admin.utils.RedisUtil;
import top.huntwolf.admin.utils.TokenUtil;
import top.huntwolf.admin.utils.WxPayUtil;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Transactional
public class WxPayService {

    @Value("${wechat.appid}")
    private String appId;

    @Value("${wechat.mchId}")
    private String mchId;

    @Value("${wechat.call-back-ip}")
    private String callBackIp;

    @Autowired
    private WxPayUtil wxPayUtil;

    @Autowired
    private WxPayNotifyDao wxPayNotifyDao;

    @Autowired
    private WxPayRefundDao wxPayRefundDao;

    @Autowired
    private CMSOrderService cmsOrderService;

    @Autowired
    private OrderService orderService;

    @Autowired
    private BookService bookService;

    @Autowired
    private RedisUtil redisUtil;


    public Map<String, String> wxPayPlaceOrder(Order order){

        //判断订单是否过期
        if (orderService.queryBooksInOrder(order.getOrderId()).getOrderStatus().equals(OrderStatus.INCOMPLETE)){
            throw new ServiceException(CodeMsg.ORDER_EXPIRATION);
        }

        order = (Order) redisUtil.get("order-" + TokenUtil.getTokenOpenId() +"-" + order.getOrderId() +"-0");

        WxPayJSAPI wxPayJSAPI = new WxPayJSAPI();

        wxPayJSAPI.setAppid(appId);
        wxPayJSAPI.setMchid(mchId);

        //设置描述信息
        if(order.getBooks().size()==1){
            wxPayJSAPI.setDescription("岛上有家书店-"+order.getBooks().get(0).getBuyBook().getTitle());
        }else {
            wxPayJSAPI.setDescription("岛上有家书店-" + order.getBooks().get(0).getBuyBook().getTitle() + "等");
        }
        //设置订单id
        wxPayJSAPI.setOut_trade_no(order.getOrderId());

        //设置订单回调ip
        wxPayJSAPI.setNotify_url("https://"+callBackIp+"/wxPay/callback");

        //将支付金额转化为分
        DecimalFormat df = new DecimalFormat("#.00");
        double price = Double.parseDouble(df.format(NumberUtils.createNumber(order.getMoney())));
        int money = (int)(price * 100);
        Map<String,Object> amount = new HashMap<>();
        amount.put("total",money);
        wxPayJSAPI.setAmount(amount);

        Map<String,String> payer = new HashMap<>();
        payer.put("openid",TokenUtil.getTokenOpenId());
        wxPayJSAPI.setPayer(payer);

        //调用jsApi生成预支付订单
        WxPrePay wxPrePay = wxPayUtil.jsApi(wxPayJSAPI);
        //生成带签名支付信息
        return wxPayUtil.getWxPaySignRequest(wxPrePay.getPrepayId(), order.getOrderId());

    }

    public void processPayNotice(HttpServletRequest httpServletRequest) throws IOException {

        WxPayNotify wxPayNotify = wxPayUtil.notificationHandler(httpServletRequest,WxPayNotify.class);
        Order order = orderService.queryStoreByOrder(wxPayNotify.getOut_trade_no(),wxPayNotify.getPayer().get("openid"));
        wxPayNotify.setStoreId(order.getStoreId());
        bookService.completeOrderIncrease(order);
        //将回调订单信息存入数据库中
        wxPayNotifyDao.insert(wxPayNotify);
        //更新订单和商品信息
        if (wxPayNotify.getTrade_state().equals("SUCCESS")){
            orderService.generatePaymentOrder(wxPayNotify.getOut_trade_no(),wxPayNotify.getPayer().get("openid"));
        }
    }

    public void processRefundNotice(HttpServletRequest httpServletRequest) throws IOException {

        WxPayRefundNotify refundNotify = wxPayUtil.notificationHandler(httpServletRequest,WxPayRefundNotify.class);

        wxPayRefundDao.update(refundNotify);

        if(refundNotify.getRefundStatus().equals("SUCCESS")){
            cmsOrderService.updateOrders(refundNotify.getOutTradeNo(),OrderStatus.REFUND);
        }


    }

    public void processPayClose(String orderId){
        wxPayUtil.closeOrder(orderId);
    }

    public void wxPayRefund(WxPayRefundOrder order){

        WxPayRefundRequest refundRequest = new WxPayRefundRequest();

        refundRequest.setTransactionId(wxPayNotifyDao.selectTransactionId(order.getOrderId()));
        refundRequest.setOutTradeNo(order.getOrderId());
        refundRequest.setOutRefundNo(order.getOrderId());
        refundRequest.setReason(order.getReason());
        refundRequest.setNotifyUrl("https://"+callBackIp+"/wxPay/refund/callback");
        Map<String,Object> amount = new HashMap<>();
        amount.put("refund",order.getRefund());
        amount.put("total",order.getTotal());
        amount.put("currency","CNY");
        refundRequest.setAmount(amount);

        WxPayRefundResult refundResult = wxPayUtil.wxPayRefund(refundRequest);

        //将退款信息存入数据库中
        wxPayRefundDao.insert(refundResult);
    }

    public WxPayRefundResult getWxPayRefund(String orderId){
        return wxPayUtil.selectSingleRefund(orderId);
    }
}
